package com.ecar.common.util;

import com.google.zxing.BarcodeFormat;
import com.google.zxing.EncodeHintType;
import com.google.zxing.MultiFormatWriter;
import com.google.zxing.common.BitMatrix;
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;
import org.krysalis.barcode4j.HumanReadablePlacement;
import org.krysalis.barcode4j.impl.code128.Code128Bean;
import org.krysalis.barcode4j.output.bitmap.BitmapCanvasProvider;
import org.springframework.web.multipart.commons.CommonsMultipartFile;
import sun.misc.BASE64Decoder;

import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.OutputStream;
import java.util.Hashtable;

/**
 * Created by admin on 2016/6/30.
 */
public class FileTool {

	private static OutputStream outputStream(String filename, String dir) throws FileNotFoundException {
		File directory = new File(dir);
		if (!directory.exists() && !directory.isDirectory()) {
			directory.mkdirs();
		}

		return new FileOutputStream(dir + "/" + filename);
	}

	private static File outputFile(String filename, String dir) throws FileNotFoundException {
		File directory = new File(dir);
		if (!directory.exists() && !directory.isDirectory()) {
			directory.mkdirs();
		}

		return new File(dir + "/" + filename);
	}

	/**
	 * 保存上传的文件
	 * @param filename
	 * @param dir
	 * @param file
	 * @return
	 */
	public static boolean writeFile(String filename, String dir, CommonsMultipartFile file) {
		try {
			File out = outputFile(filename, dir);
			file.transferTo(out);
			return true;
		} catch (Exception e) {
			e.printStackTrace();
			return false;
		}
	}

	/**
	 * base64字符串转图片文件
	 * @param filename
	 * @param dir
	 * @param base64
	 * @return
	 */
	public static boolean base64ToImageFile(String filename, String dir, String base64) {
		if (StringUtil.isEmpty(base64)) return false;

		try (OutputStream out = outputStream(filename, dir)) {
			// Base64解码
			byte[] bytes = new BASE64Decoder().decodeBuffer(base64);
			for (int i = 0; i < bytes.length; ++i) {
				if (bytes[i] < 0) {// 调整异常数据
					bytes[i] += 256;
				}
			}
			out.write(bytes);
			out.flush();
			return true;
		} catch (Exception e) {
			e.printStackTrace();
			return false;
		}
	}

	/**
	 * 生成并保存条形码jpg图片
	 * @param filepath 文件路径
	 * @param filename 文件名
	 * @param code 要生成条形码的字符串
	 * @return
	 */
	public static boolean generateBarcode128(String filename, String filepath, String code) {
		Code128Bean bean = new Code128Bean();
		final int dpi = 130;

		//barcode
		bean.setModuleWidth(0.5);
		bean.setHeight(18);
		bean.doQuietZone(true);
		bean.setQuietZone(2);//两边空白区

		//human-readable
		bean.setFontName("Helvetica");
		bean.setFontSize(3);
		bean.setMsgPosition(HumanReadablePlacement.HRP_BOTTOM);

		try (OutputStream out = outputStream(filename, filepath)) {
			BitmapCanvasProvider canvas = new BitmapCanvasProvider(
				out, "image/jpeg", dpi, BufferedImage.TYPE_BYTE_BINARY, true, 0);
			bean.generateBarcode(canvas, code);
			canvas.finish();
			return true;
		} catch (Exception e) {
			e.printStackTrace();
			return false;
		}
	}

	public static boolean generateQrCode(String filename, String dir, String code) {
		try {
			int width = 300;
			int height = 300;
			String format = "png";

			Hashtable<EncodeHintType, Object> hints = new Hashtable<>();
			hints.put(EncodeHintType.CHARACTER_SET, "UTF-8");
			hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H);
			hints.put(EncodeHintType.MARGIN, 2);

			BitMatrix bitMatrix = new MultiFormatWriter().encode(code, BarcodeFormat.QR_CODE, width, height, hints);
			File out = outputFile(filename, dir);
			MatrixToImageWriter.writeToFile(bitMatrix, format, out);
			return true;
		} catch (Exception e) {
			e.printStackTrace();
		}
		return false;
	}

	public static boolean generateQrCode(String filename, String dir, String content, String withText) {
		try {
			final int square = 800;
			final int zoom = 400;
			String format = "png";

			Hashtable<EncodeHintType, Object> hints = new Hashtable<>();
			hints.put(EncodeHintType.CHARACTER_SET, "UTF-8");
			hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H);
			hints.put(EncodeHintType.MARGIN, 2);

			BitMatrix bitMatrix = new MultiFormatWriter().encode(content, BarcodeFormat.QR_CODE, square, square, hints);
			BufferedImage unprocessed = MatrixToImageWriter.toBufferedImage(bitMatrix);
			BufferedImage result = new ImageProcesser(unprocessed).drawCenterText(withText).zoom(zoom, zoom).done();
			ImageIO.write(result, format, outputStream(filename, dir));
			return true;
		} catch (Exception e) {
			e.printStackTrace();
		}
		return false;
	}

	public static void main(String[] args) {
		generateQrCode("passenger.png", "C:\\Users\\madoka\\Documents\\Workspace\\DarkSide", "https://wx.hbglky.com/wap/client.html", "湖北客运");
	}
}
